package thread.safe;

import interface_test.sharp.C;

/**
 * @author yuisama
 * @date 2022/06/23 19:16
 **/
public class Reentrant {
    public static void main(String[] args) {
//        Counter counter1 = new Counter();
//        Thread t1 = new Thread(() -> {
//            counter1.increase();
//        });
//        t1.start();
//        Counter counter2 = new Counter();
//        Thread t2 = new Thread(() -> {
//            counter1.increase();
//        });
//        t2.start();
        Counter counter1 = new Counter();
        Counter counter2 = new Counter();
        Counter counter3 = new Counter();
        Thread t1 = new Thread(() -> {
            counter1.increase4();
        },"t1");
        Thread t2 = new Thread(() -> {
            counter2.increase4();
        },"t2");
        Thread t3 = new Thread(() -> {
            counter3.increase4();
        },"t3");
        t1.start();
        t2.start();
        t3.start();
    }
    private static class Counter {
        int val;
        int val2;
        // 方法上没加synchronized关键字，因此所有线程都可以并发进入increase4方法
        void increase4() {
            System.out.println(val);
            System.out.println(val2);
            System.out.println("鹏哥真帅呀");
            // 同步代码块，进入同步代码块，必须获取到指定的锁
//             this表示当前对象引用 ~~，锁的就是当前对象
            // 若锁的是class对象，全局唯一
            synchronized (Reentrant.class) {
                while (true) {
                    System.out.println(Thread.currentThread().getName() + "获取到当前对象的锁");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }

        // 当synchronized修饰静态方法，则相当于将Counter这个类的所有对象都给锁了(其实锁的Counter类的class对象，全局唯一)
        synchronized static void increase2() {
            while (true) {
                System.out.println(Thread.currentThread().getName() + "获取到了锁~~");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        // 锁的是当前Counter对象
        synchronized void increase() {
            val ++;
        }
        // 也是锁的Counter对象
        synchronized void increase1() {
            val2 ++;
            // 就相当于对同一个Counter对象加了两次锁 ~
            // 若线程1进入了increase1方法，若不支持可重入，进入increase需要再次获取锁，无法进入increase
            // 线程1-拿到当前Counter对象锁的线程阻塞在这里，等待线程1自己释放锁之后再进入increase() -> 这个程序永远不会停止
            // 线程1一直阻塞在这里 - 死锁
            increase();
        }
    }
}